package com.gamefx.engine1.display
{
	import com.gamefx.engine1.consts.ActionConst;
	import com.gamefx.engine1.consts.DirectionConst;
	import com.gamefx.engine1.managers.TimerManager;
	import com.gamefx.utils.ArrayEx;
	
	import flash.display.BitmapData;
	import flash.display.FrameLabel;
	import flash.display.MovieClip;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;
	import flash.utils.Endian;

	public class BMFParser
	{
		private static var matrix:Matrix = new Matrix();

		public static function readBMFInfo(bytes:ByteArray, bitmapClipData:BitmapClipData):void
		{
			bytes.endian = Endian.LITTLE_ENDIAN;
			bytes.position = 1;

			bitmapClipData.labels = new ArrayEx();
			//TODO
		}

		public static function createBMFInfo(bitmapClipData:BitmapClipData):void
		{
			bitmapClipData.labels = new ArrayEx();

			var mc:MovieClip = bitmapClipData.source;
			var label:FrameLabel, bmfLabel:BMFLabel;
			var regExp:RegExp = /[\u4e00-\u9fa5]/ig;

			for (var i:int = 0; i < mc.currentLabels.length; i++)
			{
				label = mc.currentLabels[i] as FrameLabel;

				if (!regExp.test(label.name))
				{
					bmfLabel = new BMFLabel();
					bmfLabel.name = (label.name.indexOf("#") == -1) ? label.name + "#" + DirectionConst.E : label.name;
					bmfLabel.frame = label.frame;
					bitmapClipData.labels.proxy[bmfLabel.name] = bmfLabel; //兼容无方向的SWF
				}
			}

			//兼容普通SWF
			if (bitmapClipData.labels.length == 0)
			{
				bmfLabel = new BMFLabel();
				bmfLabel.frame = 1;
				bmfLabel.totalFrames = mc.totalFrames;
				bmfLabel.name = ((bmfLabel.totalFrames == 1) ? ActionConst.ACTION_STATIC : ActionConst.ACTION_MOTION) + "#" + DirectionConst.E;
				bitmapClipData.labels.proxy[bmfLabel.name] = bmfLabel;
				return;
			}

			var avgLen:int = Math.floor(mc.totalFrames / bitmapClipData.labels.length);
			var subMc:MovieClip;
			for (i = 0; i < bitmapClipData.labels.length; i++)
			{
				bmfLabel = bitmapClipData.labels[i] as BMFLabel;

				if (i < bitmapClipData.labels.length - 1)
				{
					bmfLabel.totalFrames = bitmapClipData.labels[i + 1].frame - bmfLabel.frame;
				}
				else
				{
					bmfLabel.totalFrames = mc.totalFrames - bmfLabel.frame + 1;
				}

				if (avgLen == 1 && bmfLabel.totalFrames > 1)
				{
					bmfLabel.totalFrames = 1;
					trace("WARNING: 您可能采用了单帧嵌入MovieClip的方式，但是 [name=" + bmfLabel.name + ", frame=" + bmfLabel.frame + "] 处的长度似乎不正确。" + bitmapClipData.url);
				}
			}

			if (bitmapClipData.labels.length < mc.currentLabels.length && mc.currentLabels.length % 2 != 0)
			{
				trace("WARNING: 您可能采用了两层帧标签（一层为中文注释）的方式，但是两层的标签数量不一致，这可能会导致解析不准确。" + bitmapClipData.url);
			}
		}

		public static function parse(bitmapClipData:BitmapClipData, parseCompleteCallBack:Function):void
		{
			var mc:MovieClip = bitmapClipData.source;
			var currentBMFLabel:BMFLabel;
			var i:int = 0;

			doNextLabel();

			/**
			 * 处理一个标签（一个动作）
			 */
			function doNextLabel():void
			{
				if (i >= bitmapClipData.labels.length)
				{
					bitmapClipData.source = null;
					bitmapClipData.ready = true;
					if (parseCompleteCallBack != null)
					{
						parseCompleteCallBack();
					}
					return;
				}

				currentBMFLabel = bitmapClipData.labels[i] as BMFLabel;

				if (currentBMFLabel.totalFrames == 1) //单帧嵌套MC
				{
					mc.gotoAndStop(currentBMFLabel.frame);
					TimerManager.setTimeout(doNextLabelDelay, 50, 0);
				}
				else
				{
					snapshotOneLabel(mc, currentBMFLabel.frame, currentBMFLabel.totalFrames);
					i++;
					doNextLabel();
				}
			}

			/**
			 * 单帧嵌套MC是，不能立即读取到该MC的实例，所以延时
			 */
			function doNextLabelDelay(tryCount:int):void
			{
				var subMc:MovieClip = mc.getChildAt(0) as MovieClip;
				if (subMc != null)
				{
					if (mc.numChildren != 1)
					{
						trace("WARNING: ", currentBMFLabel, "该动作只有一帧，但帧嵌入MovieClip超过1个，这可能会导致解析不准确。" + bitmapClipData.url);
					}
					snapshotOneLabel(subMc, 1, subMc.totalFrames);

				}
				else
				{
					if (++tryCount < 10)
					{
						TimerManager.setTimeout(doNextLabelDelay, 50, tryCount);
					}
					else
					{
						trace("WARNING: ", currentBMFLabel, "解析失败！该动作只有一帧，但无法找到子MovieClip。" + bitmapClipData.url);
						i++;
						doNextLabel();
					}
				}
			}

			/**
			 * 对动作的序列帧进行快照
			 */
			function snapshotOneLabel(movieclip:MovieClip, startFrame:int, totalFrames:int):void
			{
				//trace("动作:", currentBMFLabel.name, "位置:", currentBMFLabel.frame, "动作帧数:", totalFrames);

				var prevFrameBitmap:BitmapData;
				var prevFrameIndex:int;
				var currFrameBitmap:BitmapData;
				var temp:BitmapData;
				var bound:Rectangle;
				var currentRect:*;
				var point:Point = new Point();
				var bitmaps:Array;
				var isNoBMFInfo:Boolean = (currentBMFLabel.rects == null);

				bitmapClipData.bitmaps[currentBMFLabel.name] = bitmaps = new Array(totalFrames);

				if (isNoBMFInfo)
				{
					currentBMFLabel.totalFrames = totalFrames;
					currentBMFLabel.rects = new Array(totalFrames);
					currentBMFLabel.offsetX = movieclip.x;
					currentBMFLabel.offsetY = movieclip.y;
				}

				doNextFrame(currentBMFLabel, startFrame);

				function doNextFrame(currentBMFLabel:BMFLabel, frame:int):void
				{
					if (frame > startFrame + totalFrames)
					{
						i++;
						doNextLabel();
						return;
					}

					movieclip.gotoAndStop(frame);

					if (isNoBMFInfo)
					{
						bound = movieclip.getBounds(movieclip);
						currFrameBitmap = new BitmapData(Math.ceil(bound.right), Math.ceil(bound.bottom), true, 0x00000000);
						currFrameBitmap.draw(movieclip);

						//图像是否与前一帧相同
						if (prevFrameBitmap != null && currFrameBitmap.compare(prevFrameBitmap) == 0x00000000)
						{
							currFrameBitmap = prevFrameBitmap;
							currentRect = prevFrameIndex;
						}
						else
						{
							prevFrameBitmap = currFrameBitmap;
							prevFrameIndex = frame - startFrame;
						}

						//裁剪空白区域
						if (currFrameBitmap != null)
						{
							currentRect = currFrameBitmap.getColorBoundsRect(0xFF000000, 0x00000000, false);
							if (currentRect.width > 0 && currentRect.height > 0)
							{
								temp = new BitmapData(currentRect.width, currentRect.height, true, 0x00000000);
								temp.copyPixels(currFrameBitmap, currentRect, point);
								currFrameBitmap = temp;
							}
						}

						currentBMFLabel.rects[frame - startFrame] = currentRect;
					}
					else
					{
						//按BMFInfo直接读取
						currentRect = currentBMFLabel.rects[frame];
						if (currentRect != null)
						{
							if (isNaN(currentRect) == false)
							{
								currentRect = currentBMFLabel.rects[currentRect];
							}

							BMFParser.matrix.tx = -currentRect.x;
							BMFParser.matrix.ty = -currentRect.y;
							currFrameBitmap = new BitmapData(currentRect.width, currentRect.height, true, 0x00000000);
							currFrameBitmap.draw(movieclip, BMFParser.matrix);
						}
						else
						{
							currFrameBitmap = null;
						}
					}

					bitmaps[frame - startFrame] = currFrameBitmap;
					TimerManager.setTimeout(doNextFrame, 10, currentBMFLabel, ++frame);
//					doNextFrame(currentBMFLabel, ++frame); //高CPU占用率
				}

			}

		} /* end parse */


	}
}
